package com.zyl.blog.common.validated;

import com.zyl.blog.common.config.anno.FileConstraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.web.multipart.MultipartFile;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @version v1.0
 * @ProjectName: Personal_Blog
 * @Package: com.zyl.common.validated
 * @ClassName: FileValidator
 * @Description: 文件验证器
 * @Author FinalFantasy
 * @Date 2025/3/10-22:04
 */
public class FileValidator implements ConstraintValidator<FileConstraint, MultipartFile> {
    private long maxBytes;

    @Override
    public void initialize(FileConstraint constraint) {
        this.maxBytes = parseSize(constraint.maxSize());
    }

    @Override
    public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
        if (file == null || file.isEmpty()) return false;
        return file.getSize() <= maxBytes;
    }

    private long parseSize(String size) {
        // 空值防御
        if (size == null || size.trim().isEmpty()) {
            throw new IllegalArgumentException("文件大小配置不能为空");
        }

        // 统一转为大写并去除空格
        String cleanSize = size.trim().toUpperCase();

        // 正则表达式匹配数字+单位格式
        Matcher matcher = Pattern.compile("^(\\d+)([BKMGTP]B?)?$").matcher(cleanSize);
        if (!matcher.find()) {
            throw new IllegalArgumentException("无效的文件大小格式: " + size);
        }

        long numericValue = Long.parseLong(matcher.group(1));
        if (numericValue <= 0) {
            throw new IllegalArgumentException("文件大小必须大于0: " + size);
        }

        String unit = matcher.group(2) != null ? matcher.group(2) : "B";

        // 根据单位计算乘数
        return switch (unit) {
            case "B" -> numericValue;
            case "KB", "K" -> numericValue * 1024L;
            case "MB", "M" -> numericValue * 1024L * 1024;
            case "GB", "G" -> numericValue * 1024L * 1024 * 1024;
            case "TB", "T" -> numericValue * 1024L * 1024 * 1024 * 1024;
            case "PB", "P" -> numericValue * 1024L * 1024 * 1024 * 1024 * 1024;
            default -> throw new IllegalArgumentException("不支持的文件大小单位: " + unit);
        };
    }
}
